fgetpos関数、fsetpos関数を使って、ファイルの入力・出力位置(ファイルオフセット)を制御することができます。fgetpos関数は現在のファイルオフセットを取得し、fsetpos関数はファイルオフセットを設定します。

同じような機能のfseek関数との相違は、fseek関数はファイルオフセットをlong int型で指定するため、ファイルの大きさは約2GBまで(long int型が4バイト長の場合)となります。これに対して、fgetpos関数とfsetpos関数はファイルオフセットを専用の構造体で管理することにより、2GB以上のファイルも取り扱えるようになっています。

#include <stdio.h>
int fgetpos(FILE *stream, fpos_t *pos);
int fsetpos(FILE *stream, fpos_t *pos);

*streamはfopen関数で取得した、ファイルポインタを指定します。
*posはファイルオフセットを格納する構造体オブジェクトを指定します。

戻り値として、正常に処理ができた場合は0を返します。

次の例題プログラムは、入力したデータの英小文字を英大文字に変換した後、同じ場所にデータを出力することにより、ファイル内の英字を大文字にしています。ファイルの更新を行うため、fopen関数のオープンモードは’r+’になっています。

プログラム 例

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define SIZE 1024

nt main(int argc, char **argv)
{
  FILE    *fp;
  fpos_t  pos;
  char    buff[SIZE];
  char    *p_buff;

  if (argc == 2) {
    if ((fp = fopen(*(argv+1), 'r+')) != NULL) {
      /* 現在のファイルオフセットの取得 */
      if (fgetpos(fp, &pos) != 0) {
        printf('ファイルオフセットの取得に失敗しました\n');
        exit(3);
      }
      while(fgets(buff, SIZE, fp) != NULL) {
        /* 英小文字を英大文字に変換 */
        for (p_buff = buff; *p_buff; ++p_buff) {
          *p_buff = toupper(*p_buff);
        }

        /* ファイルオフセットを入力データの先頭位置に戻す */
        if (fsetpos(fp, &pos) != 0) {
          printf('ファイルオフセットの設定に失敗しました\n');
          exit(3);
        }

        if (fputs(buff, fp) == EOF) {
          printf('ファイルの出力を失敗しました\n');
          exit(1);
        }

        /* 現在のファイルオフセットの取得 */
        if (fgetpos(fp, &pos) != 0) {
          printf('ファイルオフセットの取得に失敗しました\n');
          exit(3);
        }
      }

      fclose(fp);
    }
    else {
      printf('ファイルのオープンに失敗しました\n');
      exit(1);
    }
  }
  else {
    printf('実行時引数の数が不当です\n');
    exit(2);
  }

  return 0;
}

例の実行結果

$ cat temp_1.txt
#include <stdio.h>

int main()
{
  printf('Hello World!!.\n');

  return 0;
}
$
$ ./fgetpos.exe temp_1.txt
$
$ cat temp_1.txt
#INCLUDE <STDIO.H>

INT MAIN()
{
  PRINTF('HELLO WORLD!!.\N');

  RETURN 0;
}
$